/*
 * %W% %E%
 *
 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.lang;

import sun.misc.FloatingDecimal;
import java.util.Arrays;

/**
 * A mutable sequence of characters.
 * <p>
 * Implements a modifiable string. At any point in time it contains some
 * particular sequence of characters, but the length and content of the sequence
 * can be changed through certain method calls.
 *
 * @author Michael McCloskey
 * @version %I%, %G%
 * @since 1.5
 */
abstract class AbstractStringBuilder implements Appendable, CharSequence {
	/**
	 * The value is used for character storage. 存储字符的数组
	 */
	char value[];

	/**
	 * The count is the number of characters used. 数组内使用的字符数
	 */
	int count;

	/**
	 * This no-arg constructor is necessary for serialization of subclasses.
	 */
	AbstractStringBuilder() {
	}

	/**
	 * Creates an AbstractStringBuilder of the specified capacity.
	 */
	AbstractStringBuilder(int capacity) {
		value = new char[capacity];
	}

	// 两个构造函数

	/**
	 * Returns the length (character count).
	 *
	 * @return the length of the sequence of characters currently represented by
	 *         this object
	 */
	public int length() {
		return count;
	}

	/**
	 * Returns the current capacity. The capacity is the amount of storage
	 * available for newly inserted characters, beyond which an allocation will
	 * occur.
	 *
	 * @return the current capacity
	 */
	public int capacity() {
		return value.length;
	}

	/**
	 * Ensures that the capacity is at least equal to the specified minimum. If
	 * the current capacity is less than the argument, then a new internal array
	 * is allocated with greater capacity. The new capacity is the larger of:
	 * <ul>
	 * <li>The <code>minimumCapacity</code> argument.
	 * <li>Twice the old capacity, plus <code>2</code>.
	 * </ul>
	 * If the <code>minimumCapacity</code> argument is nonpositive, this method
	 * takes no action and simply returns.
	 *
	 * @param minimumCapacity
	 *            the minimum desired capacity.
	 */
	public void ensureCapacity(int minimumCapacity) {
		if (minimumCapacity > value.length) {
			expandCapacity(minimumCapacity);
		}
	}

	/**
	 * This implements the expansion semantics of ensureCapacity with no size
	 * check or synchronization.
	 */
	void expandCapacity(int minimumCapacity) {
		int newCapacity = (value.length + 1) * 2;
		//溢出，取最大Integer
		if (newCapacity < 0) {
			newCapacity = Integer.MAX_VALUE;
		} else if (minimumCapacity > newCapacity) {
			//所以传入的是最小的大小，实际大小可能大于 传入参数
			newCapacity = minimumCapacity;
		}
		//复制新数组
		value = Arrays.copyOf(value, newCapacity);
	}

	/**
	 * Attempts to reduce storage used for the character sequence. If the buffer
	 * is larger than necessary to hold its current sequence of characters, then
	 * it may be resized to become more space efficient. Calling this method
	 * may, but is not required to, affect the value returned by a subsequent
	 * call to the {@link #capacity()} method.
	 */
	//减少数组大小至实际使用大小，因为int newCapacity = (value.length + 1) * 2;
	public void trimToSize() {
		if (count < value.length) {
			value = Arrays.copyOf(value, count);
		}
	}

	/**
	 * Sets the length of the character sequence. The sequence is changed to a
	 * new character sequence whose length is specified by the argument. For
	 * every nonnegative index <i>k</i> less than <code>newLength</code>, the
	 * character at index <i>k</i> in the new character sequence is the same as
	 * the character at index <i>k</i> in the old sequence if <i>k</i> is less
	 * than the length of the old character sequence; otherwise, it is the null
	 * character <code>'&#92;u0000'</code>.
	 * 
	 * In other words, if the <code>newLength</code> argument is less than the
	 * current length, the length is changed to the specified length.
	 * <p>
	 * If the <code>newLength</code> argument is greater than or equal to the
	 * current length, sufficient null characters (<code>'&#92;u0000'</code>)
	 * are appended so that length becomes the <code>newLength</code> argument.
	 * <p>
	 * The <code>newLength</code> argument must be greater than or equal to
	 * <code>0</code>.
	 *
	 * @param newLength
	 *            the new length
	 * @throws IndexOutOfBoundsException
	 *             if the <code>newLength</code> argument is negative.
	 */
	public void setLength(int newLength) {
		if (newLength < 0)
			throw new StringIndexOutOfBoundsException(newLength);
		if (newLength > value.length)
			//扩展大小
			expandCapacity(newLength);

		//数组实际char后全置位\0，但是置了count = newLength
		if (count < newLength) {
			for (; count < newLength; count++)
				value[count] = '\0';
		} else {
			count = newLength;
		}
	}

	/**
	 * Returns the <code>char</code> value in this sequence at the specified
	 * index. The first <code>char</code> value is at index <code>0</code>, the
	 * next at index <code>1</code>, and so on, as in array indexing.
	 * <p>
	 * The index argument must be greater than or equal to <code>0</code>, and
	 * less than the length of this sequence.
	 *
	 * <p>
	 * If the <code>char</code> value specified by the index is a <a
	 * href="Character.html#unicode">surrogate</a>, the surrogate value is
	 * returned.
	 *
	 * @param index
	 *            the index of the desired <code>char</code> value.
	 * @return the <code>char</code> value at the specified index.
	 * @throws IndexOutOfBoundsException
	 *             if <code>index</code> is negative or greater than or equal to
	 *             <code>length()</code>.
	 */
	//read Point
	public char charAt(int index) {
		if ((index < 0) || (index >= count))
			throw new StringIndexOutOfBoundsException(index);
		return value[index];
	}

	/**
	 * Returns the character (Unicode code point) at the specified index. The
	 * index refers to <code>char</code> values (Unicode code units) and ranges
	 * from <code>0</code> to {@link #length()}<code> - 1</code>.
	 *
	 * <p>
	 * If the <code>char</code> value specified at the given index is in the
	 * high-surrogate range, the following index is less than the length of this
	 * sequence, and the <code>char</code> value at the following index is in
	 * the low-surrogate range, then the supplementary code point corresponding
	 * to this surrogate pair is returned. Otherwise, the <code>char</code>
	 * value at the given index is returned.
	 *
	 * @param index
	 *            the index to the <code>char</code> values
	 * @return the code point value of the character at the <code>index</code>
	 * @exception IndexOutOfBoundsException
	 *                if the <code>index</code> argument is negative or not less
	 *                than the length of this sequence.
	 */
	public int codePointAt(int index) {
		if ((index < 0) || (index >= count)) {
			throw new StringIndexOutOfBoundsException(index);
		}
		return Character.codePointAt(value, index);
	}

	/**
	 * Returns the character (Unicode code point) before the specified index.
	 * The index refers to <code>char</code> values (Unicode code units) and
	 * ranges from <code>1</code> to {@link #length()}.
	 *
	 * <p>
	 * If the <code>char</code> value at <code>(index - 1)</code> is in the
	 * low-surrogate range, <code>(index - 2)</code> is not negative, and the
	 * <code>char</code> value at <code>(index -
	 * 2)</code> is in the high-surrogate range, then the supplementary code
	 * point value of the surrogate pair is returned. If the <code>char</code>
	 * value at <code>index -
	 * 1</code> is an unpaired low-surrogate or a high-surrogate, the surrogate
	 * value is returned.
	 *
	 * @param index
	 *            the index following the code point that should be returned
	 * @return the Unicode code point value before the given index.
	 * @exception IndexOutOfBoundsException
	 *                if the <code>index</code> argument is less than 1 or
	 *                greater than the length of this sequence.
	 */
	public int codePointBefore(int index) {
		int i = index - 1;
		if ((i < 0) || (i >= count)) {
			throw new StringIndexOutOfBoundsException(index);
		}
		return Character.codePointBefore(value, index);
	}

	/**
	 * Returns the number of Unicode code points in the specified text range of
	 * this sequence. The text range begins at the specified
	 * <code>beginIndex</code> and extends to the <code>char</code> at index
	 * <code>endIndex - 1</code>. Thus the length (in <code>char</code>s) of the
	 * text range is <code>endIndex-beginIndex</code>. Unpaired surrogates
	 * within this sequence count as one code point each.
	 *
	 * @param beginIndex
	 *            the index to the first <code>char</code> of the text range.
	 * @param endIndex
	 *            the index after the last <code>char</code> of the text range.
	 * @return the number of Unicode code points in the specified text range
	 * @exception IndexOutOfBoundsException
	 *                if the <code>beginIndex</code> is negative, or
	 *                <code>endIndex</code> is larger than the length of this
	 *                sequence, or <code>beginIndex</code> is larger than
	 *                <code>endIndex</code>.
	 */
	public int codePointCount(int beginIndex, int endIndex) {
		if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
			throw new IndexOutOfBoundsException();
		}
		return Character.codePointCountImpl(value, beginIndex, endIndex
				- beginIndex);
	}

	/**
	 * Returns the index within this sequence that is offset from the given
	 * <code>index</code> by <code>codePointOffset</code> code points. Unpaired
	 * surrogates within the text range given by <code>index</code> and
	 * <code>codePointOffset</code> count as one code point each.
	 *
	 * @param index
	 *            the index to be offset
	 * @param codePointOffset
	 *            the offset in code points
	 * @return the index within this sequence
	 * @exception IndexOutOfBoundsException
	 *                if <code>index</code> is negative or larger then the
	 *                length of this sequence, or if
	 *                <code>codePointOffset</code> is positive and the
	 *                subsequence starting with <code>index</code> has fewer
	 *                than <code>codePointOffset</code> code points, or if
	 *                <code>codePointOffset</code> is negative and the
	 *                subsequence before <code>index</code> has fewer than the
	 *                absolute value of <code>codePointOffset</code> code
	 *                points.
	 */
	public int offsetByCodePoints(int index, int codePointOffset) {
		if (index < 0 || index > count) {
			throw new IndexOutOfBoundsException();
		}
		return Character.offsetByCodePointsImpl(value, 0, count, index,
				codePointOffset);
	}

	/**
	 * Characters are copied from this sequence into the destination character
	 * array <code>dst</code>. The first character to be copied is at index
	 * <code>srcBegin</code>; the last character to be copied is at index
	 * <code>srcEnd-1</code>. The total number of characters to be copied is
	 * <code>srcEnd-srcBegin</code>. The characters are copied into the subarray
	 * of <code>dst</code> starting at index <code>dstBegin</code> and ending at
	 * index:
	 * <p>
	 * <blockquote>
	 * 
	 * <pre>
	 * dstbegin + (srcEnd - srcBegin) - 1
	 * </pre>
	 * 
	 * </blockquote>
	 *
	 * @param srcBegin
	 *            start copying at this offset.
	 * @param srcEnd
	 *            stop copying at this offset.
	 * @param dst
	 *            the array to copy the data into.
	 * @param dstBegin
	 *            offset into <code>dst</code>.
	 * @throws NullPointerException
	 *             if <code>dst</code> is <code>null</code>.
	 * @throws IndexOutOfBoundsException
	 *             if any of the following is true:
	 *             <ul>
	 *             <li><code>srcBegin</code> is negative <li><code>dstBegin
	 *             </code> is negative <li>the <code>srcBegin</code> argument is
	 *             greater than the <code>srcEnd</code> argument. <li><code>
	 *             srcEnd</code> is greater than <code>this.length()</code>. 
	 *             <li><code>dstBegin+srcEnd-srcBegin</code> is greater than
	 *             <code>dst.length</code>
	 *             </ul>
	 */
	public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
		if (srcBegin < 0)
			throw new StringIndexOutOfBoundsException(srcBegin);
		if ((srcEnd < 0) || (srcEnd > count))
			throw new StringIndexOutOfBoundsException(srcEnd);
		if (srcBegin > srcEnd)
			throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
		System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
	}

	/**
	 * The character at the specified index is set to <code>ch</code>. This
	 * sequence is altered to represent a new character sequence that is
	 * identical to the old character sequence, except that it contains the
	 * character <code>ch</code> at position <code>index</code>.
	 * <p>
	 * The index argument must be greater than or equal to <code>0</code>, and
	 * less than the length of this sequence.
	 *
	 * @param index
	 *            the index of the character to modify.
	 * @param ch
	 *            the new character.
	 * @throws IndexOutOfBoundsException
	 *             if <code>index</code> is negative or greater than or equal to
	 *             <code>length()</code>.
	 */
	public void setCharAt(int index, char ch) {
		if ((index < 0) || (index >= count))
			throw new StringIndexOutOfBoundsException(index);
		value[index] = ch;
	}

	/**
	 * Appends the string representation of the <code>Object</code> argument.
	 * <p>
	 * The argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * appended to this sequence.
	 *
	 * @param obj
	 *            an <code>Object</code>.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(Object obj) {
		return append(String.valueOf(obj));
	}

	/**
	 * Appends the specified string to this character sequence.
	 * <p>
	 * The characters of the <code>String</code> argument are appended, in
	 * order, increasing the length of this sequence by the length of the
	 * argument. If <code>str</code> is <code>null</code>, then the four
	 * characters <code>"null"</code> are appended.
	 * <p>
	 * Let <i>n</i> be the length of this character sequence just prior to
	 * execution of the <code>append</code> method. Then the character at index
	 * <i>k</i> in the new character sequence is equal to the character at index
	 * <i>k</i> in the old character sequence, if <i>k</i> is less than
	 * <i>n</i>; otherwise, it is equal to the character at index <i>k-n</i> in
	 * the argument <code>str</code>.
	 *
	 * @param str
	 *            a string.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(String str) {
		if (str == null)
			str = "null";
		int len = str.length();
		if (len == 0)
			return this;
		int newCount = count + len;
		if (newCount > value.length)
			expandCapacity(newCount);
		str.getChars(0, len, value, count);
		count = newCount;
		return this;
	}

	// Documentation in subclasses because of synchro difference
	public AbstractStringBuilder append(StringBuffer sb) {
		if (sb == null)
			return append("null");
		int len = sb.length();
		int newCount = count + len;
		if (newCount > value.length)
			expandCapacity(newCount);
		sb.getChars(0, len, value, count);
		count = newCount;
		return this;
	}

	// Documentation in subclasses because of synchro difference
	public AbstractStringBuilder append(CharSequence s) {
		if (s == null)
			s = "null";
		if (s instanceof String)
			return this.append((String) s);
		if (s instanceof StringBuffer)
			return this.append((StringBuffer) s);
		return this.append(s, 0, s.length());
	}

	/**
	 * Appends a subsequence of the specified <code>CharSequence</code> to this
	 * sequence.
	 * <p>
	 * Characters of the argument <code>s</code>, starting at index
	 * <code>start</code>, are appended, in order, to the contents of this
	 * sequence up to the (exclusive) index <code>end</code>. The length of this
	 * sequence is increased by the value of <code>end - start</code>.
	 * <p>
	 * Let <i>n</i> be the length of this character sequence just prior to
	 * execution of the <code>append</code> method. Then the character at index
	 * <i>k</i> in this character sequence becomes equal to the character at
	 * index <i>k</i> in this sequence, if <i>k</i> is less than <i>n</i>;
	 * otherwise, it is equal to the character at index <i>k+start-n</i> in the
	 * argument <code>s</code>.
	 * <p>
	 * If <code>s</code> is <code>null</code>, then this method appends
	 * characters as if the s parameter was a sequence containing the four
	 * characters <code>"null"</code>.
	 *
	 * @param s
	 *            the sequence to append.
	 * @param start
	 *            the starting index of the subsequence to be appended.
	 * @param end
	 *            the end index of the subsequence to be appended.
	 * @return a reference to this object.
	 * @throws IndexOutOfBoundsException
	 *             if <code>start</code> or <code>end</code> are negative, or
	 *             <code>start</code> is greater than <code>end</code> or
	 *             <code>end</code> is greater than <code>s.length()</code>
	 */
	public AbstractStringBuilder append(CharSequence s, int start, int end) {
		if (s == null)
			s = "null";
		if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
			throw new IndexOutOfBoundsException("start " + start + ", end "
					+ end + ", s.length() " + s.length());
		int len = end - start;
		if (len == 0)
			return this;
		int newCount = count + len;
		if (newCount > value.length)
			expandCapacity(newCount);
		for (int i = start; i < end; i++)
			value[count++] = s.charAt(i);
		count = newCount;
		return this;
	}

	/**
	 * Appends the string representation of the <code>char</code> array argument
	 * to this sequence.
	 * <p>
	 * The characters of the array argument are appended, in order, to the
	 * contents of this sequence. The length of this sequence increases by the
	 * length of the argument.
	 * <p>
	 * The overall effect is exactly as if the argument were converted to a
	 * string by the method {@link String#valueOf(char[])} and the characters of
	 * that string were then {@link #append(String) appended} to this character
	 * sequence.
	 *
	 * @param str
	 *            the characters to be appended.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(char str[]) {
		int newCount = count + str.length;
		if (newCount > value.length)
			expandCapacity(newCount);
		System.arraycopy(str, 0, value, count, str.length);
		count = newCount;
		return this;
	}

	/**
	 * Appends the string representation of a subarray of the <code>char</code>
	 * array argument to this sequence.
	 * <p>
	 * Characters of the <code>char</code> array <code>str</code>, starting at
	 * index <code>offset</code>, are appended, in order, to the contents of
	 * this sequence. The length of this sequence increases by the value of
	 * <code>len</code>.
	 * <p>
	 * The overall effect is exactly as if the arguments were converted to a
	 * string by the method {@link String#valueOf(char[],int,int)} and the
	 * characters of that string were then {@link #append(String) appended} to
	 * this character sequence.
	 *
	 * @param str
	 *            the characters to be appended.
	 * @param offset
	 *            the index of the first <code>char</code> to append.
	 * @param len
	 *            the number of <code>char</code>s to append.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(char str[], int offset, int len) {
		int newCount = count + len;
		if (newCount > value.length)
			expandCapacity(newCount);
		System.arraycopy(str, offset, value, count, len);
		count = newCount;
		return this;
	}

	/**
	 * Appends the string representation of the <code>boolean</code> argument to
	 * the sequence.
	 * <p>
	 * The argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * appended to this sequence.
	 *
	 * @param b
	 *            a <code>boolean</code>.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(boolean b) {
		if (b) {
			int newCount = count + 4;
			if (newCount > value.length)
				expandCapacity(newCount);
			value[count++] = 't';
			value[count++] = 'r';
			value[count++] = 'u';
			value[count++] = 'e';
		} else {
			int newCount = count + 5;
			if (newCount > value.length)
				expandCapacity(newCount);
			value[count++] = 'f';
			value[count++] = 'a';
			value[count++] = 'l';
			value[count++] = 's';
			value[count++] = 'e';
		}
		return this;
	}

	/**
	 * Appends the string representation of the <code>char</code> argument to
	 * this sequence.
	 * <p>
	 * The argument is appended to the contents of this sequence. The length of
	 * this sequence increases by <code>1</code>.
	 * <p>
	 * The overall effect is exactly as if the argument were converted to a
	 * string by the method {@link String#valueOf(char)} and the character in
	 * that string were then {@link #append(String) appended} to this character
	 * sequence.
	 *
	 * @param c
	 *            a <code>char</code>.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(char c) {
		int newCount = count + 1;
		if (newCount > value.length)
			expandCapacity(newCount);
		value[count++] = c;
		return this;
	}

	/**
	 * Appends the string representation of the <code>int</code> argument to
	 * this sequence.
	 * <p>
	 * The argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * appended to this sequence.
	 *
	 * @param i
	 *            an <code>int</code>.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(int i) {
		if (i == Integer.MIN_VALUE) {
			append("-2147483648");
			return this;
		}
		int appendedLength = (i < 0) ? stringSizeOfInt(-i) + 1
				: stringSizeOfInt(i);
		int spaceNeeded = count + appendedLength;
		if (spaceNeeded > value.length)
			expandCapacity(spaceNeeded);
		Integer.getChars(i, spaceNeeded, value);
		count = spaceNeeded;
		return this;
	}

	final static int[] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
			99999999, 999999999, Integer.MAX_VALUE };

	// Requires positive x
	static int stringSizeOfInt(int x) {
		for (int i = 0;; i++)
			if (x <= sizeTable[i])
				return i + 1;
	}

	/**
	 * Appends the string representation of the <code>long</code> argument to
	 * this sequence.
	 * <p>
	 * The argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * appended to this sequence.
	 *
	 * @param l
	 *            a <code>long</code>.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(long l) {
		if (l == Long.MIN_VALUE) {
			append("-9223372036854775808");
			return this;
		}
		int appendedLength = (l < 0) ? stringSizeOfLong(-l) + 1
				: stringSizeOfLong(l);
		int spaceNeeded = count + appendedLength;
		if (spaceNeeded > value.length)
			expandCapacity(spaceNeeded);
		Long.getChars(l, spaceNeeded, value);
		count = spaceNeeded;
		return this;
	}

	// Requires positive x
	static int stringSizeOfLong(long x) {
		long p = 10;
		for (int i = 1; i < 19; i++) {
			if (x < p)
				return i;
			p = 10 * p;
		}
		return 19;
	}

	/**
	 * Appends the string representation of the <code>float</code> argument to
	 * this sequence.
	 * <p>
	 * The argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * appended to this string sequence.
	 *
	 * @param f
	 *            a <code>float</code>.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(float f) {
		new FloatingDecimal(f).appendTo(this);
		return this;
	}

	/**
	 * Appends the string representation of the <code>double</code> argument to
	 * this sequence.
	 * <p>
	 * The argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * appended to this sequence.
	 *
	 * @param d
	 *            a <code>double</code>.
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder append(double d) {
		new FloatingDecimal(d).appendTo(this);
		return this;
	}

	/**
	 * Removes the characters in a substring of this sequence. The substring
	 * begins at the specified <code>start</code> and extends to the character
	 * at index <code>end - 1</code> or to the end of the sequence if no such
	 * character exists. If <code>start</code> is equal to <code>end</code>, no
	 * changes are made.
	 *
	 * @param start
	 *            The beginning index, inclusive.
	 * @param end
	 *            The ending index, exclusive.
	 * @return This object.
	 * @throws StringIndexOutOfBoundsException
	 *             if <code>start</code> is negative, greater than
	 *             <code>length()</code>, or greater than <code>end</code>.
	 */
	public AbstractStringBuilder delete(int start, int end) {
		if (start < 0)
			throw new StringIndexOutOfBoundsException(start);
		if (end > count)
			end = count;
		if (start > end)
			throw new StringIndexOutOfBoundsException();
		int len = end - start;
		if (len > 0) {
			System.arraycopy(value, start + len, value, start, count - end);
			count -= len;
		}
		return this;
	}

	/**
	 * Appends the string representation of the <code>codePoint</code> argument
	 * to this sequence.
	 *
	 * <p>
	 * The argument is appended to the contents of this sequence. The length of
	 * this sequence increases by {@link Character#charCount(int)
	 * Character.charCount(codePoint)}.
	 *
	 * <p>
	 * The overall effect is exactly as if the argument were converted to a
	 * <code>char</code> array by the method {@link Character#toChars(int)} and
	 * the character in that array were then {@link #append(char[]) appended} to
	 * this character sequence.
	 *
	 * @param codePoint
	 *            a Unicode code point
	 * @return a reference to this object.
	 * @exception IllegalArgumentException
	 *                if the specified <code>codePoint</code> isn't a valid
	 *                Unicode code point
	 */
	public AbstractStringBuilder appendCodePoint(int codePoint) {
		if (!Character.isValidCodePoint(codePoint)) {
			throw new IllegalArgumentException();
		}
		int n = 1;
		if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) {
			n++;
		}
		int newCount = count + n;
		if (newCount > value.length) {
			expandCapacity(newCount);
		}
		if (n == 1) {
			value[count++] = (char) codePoint;
		} else {
			Character.toSurrogates(codePoint, value, count);
			count += n;
		}
		return this;
	}

	/**
	 * Removes the <code>char</code> at the specified position in this sequence.
	 * This sequence is shortened by one <code>char</code>.
	 *
	 * <p>
	 * Note: If the character at the given index is a supplementary character,
	 * this method does not remove the entire character. If correct handling of
	 * supplementary characters is required, determine the number of
	 * <code>char</code>s to remove by calling
	 * <code>Character.charCount(thisSequence.codePointAt(index))</code>, where
	 * <code>thisSequence</code> is this sequence.
	 *
	 * @param index
	 *            Index of <code>char</code> to remove
	 * @return This object.
	 * @throws StringIndexOutOfBoundsException
	 *             if the <code>index</code> is negative or greater than or
	 *             equal to <code>length()</code>.
	 */
	public AbstractStringBuilder deleteCharAt(int index) {
		if ((index < 0) || (index >= count))
			throw new StringIndexOutOfBoundsException(index);
		System.arraycopy(value, index + 1, value, index, count - index - 1);
		count--;
		return this;
	}

	/**
	 * Replaces the characters in a substring of this sequence with characters
	 * in the specified <code>String</code>. The substring begins at the
	 * specified <code>start</code> and extends to the character at index
	 * <code>end - 1</code> or to the end of the sequence if no such character
	 * exists. First the characters in the substring are removed and then the
	 * specified <code>String</code> is inserted at <code>start</code>. (This
	 * sequence will be lengthened to accommodate the specified String if
	 * necessary.)
	 * 
	 * @param start
	 *            The beginning index, inclusive.
	 * @param end
	 *            The ending index, exclusive.
	 * @param str
	 *            String that will replace previous contents.
	 * @return This object.
	 * @throws StringIndexOutOfBoundsException
	 *             if <code>start</code> is negative, greater than
	 *             <code>length()</code>, or greater than <code>end</code>.
	 */
	public AbstractStringBuilder replace(int start, int end, String str) {
		if (start < 0)
			throw new StringIndexOutOfBoundsException(start);
		if (start > count)
			throw new StringIndexOutOfBoundsException("start > length()");
		if (start > end)
			throw new StringIndexOutOfBoundsException("start > end");

		if (end > count)
			end = count;
		int len = str.length();
		int newCount = count + len - (end - start);
		if (newCount > value.length)
			expandCapacity(newCount);

		System.arraycopy(value, end, value, start + len, count - end);
		str.getChars(value, start);
		count = newCount;
		return this;
	}

	/**
	 * Returns a new <code>String</code> that contains a subsequence of
	 * characters currently contained in this character sequence. The substring
	 * begins at the specified index and extends to the end of this sequence.
	 * 
	 * @param start
	 *            The beginning index, inclusive.
	 * @return The new string.
	 * @throws StringIndexOutOfBoundsException
	 *             if <code>start</code> is less than zero, or greater than the
	 *             length of this object.
	 */
	public String substring(int start) {
		return substring(start, count);
	}

	/**
	 * Returns a new character sequence that is a subsequence of this sequence.
	 *
	 * <p>
	 * An invocation of this method of the form
	 *
	 * <blockquote>
	 * 
	 * <pre>
	 * sb.subSequence(begin, end)
	 * </pre>
	 * 
	 * </blockquote>
	 *
	 * behaves in exactly the same way as the invocation
	 *
	 * <blockquote>
	 * 
	 * <pre>
	 * sb.substring(begin, end)
	 * </pre>
	 * 
	 * </blockquote>
	 *
	 * This method is provided so that this class can implement the
	 * {@link CharSequence} interface.
	 * </p>
	 *
	 * @param start
	 *            the start index, inclusive.
	 * @param end
	 *            the end index, exclusive.
	 * @return the specified subsequence.
	 *
	 * @throws IndexOutOfBoundsException
	 *             if <tt>start</tt> or <tt>end</tt> are negative, if
	 *             <tt>end</tt> is greater than <tt>length()</tt>, or if
	 *             <tt>start</tt> is greater than <tt>end</tt>
	 * @spec JSR-51
	 */
	public CharSequence subSequence(int start, int end) {
		return substring(start, end);
	}

	/**
	 * Returns a new <code>String</code> that contains a subsequence of
	 * characters currently contained in this sequence. The substring begins at
	 * the specified <code>start</code> and extends to the character at index
	 * <code>end - 1</code>.
	 *
	 * @param start
	 *            The beginning index, inclusive.
	 * @param end
	 *            The ending index, exclusive.
	 * @return The new string.
	 * @throws StringIndexOutOfBoundsException
	 *             if <code>start</code> or <code>end</code> are negative or
	 *             greater than <code>length()</code>, or <code>start</code> is
	 *             greater than <code>end</code>.
	 */
	public String substring(int start, int end) {
		if (start < 0)
			throw new StringIndexOutOfBoundsException(start);
		if (end > count)
			throw new StringIndexOutOfBoundsException(end);
		if (start > end)
			throw new StringIndexOutOfBoundsException(end - start);
		return new String(value, start, end - start);
	}

	/**
	 * Inserts the string representation of a subarray of the <code>str</code>
	 * array argument into this sequence. The subarray begins at the specified
	 * <code>offset</code> and extends <code>len</code> <code>char</code>s. The
	 * characters of the subarray are inserted into this sequence at the
	 * position indicated by <code>index</code>. The length of this sequence
	 * increases by <code>len</code> <code>char</code>s.
	 *
	 * @param index
	 *            position at which to insert subarray.
	 * @param str
	 *            A <code>char</code> array.
	 * @param offset
	 *            the index of the first <code>char</code> in subarray to be
	 *            inserted.
	 * @param len
	 *            the number of <code>char</code>s in the subarray to be
	 *            inserted.
	 * @return This object
	 * @throws StringIndexOutOfBoundsException
	 *             if <code>index</code> is negative or greater than
	 *             <code>length()</code>, or <code>offset</code> or
	 *             <code>len</code> are negative, or <code>(offset+len)</code>
	 *             is greater than <code>str.length</code>.
	 */
	public AbstractStringBuilder insert(int index, char str[], int offset,
			int len) {
		if ((index < 0) || (index > length()))
			throw new StringIndexOutOfBoundsException(index);
		if ((offset < 0) || (len < 0) || (offset > str.length - len))
			throw new StringIndexOutOfBoundsException("offset " + offset
					+ ", len " + len + ", str.length " + str.length);
		int newCount = count + len;
		if (newCount > value.length)
			expandCapacity(newCount);
		System.arraycopy(value, index, value, index + len, count - index);
		System.arraycopy(str, offset, value, index, len);
		count = newCount;
		return this;
	}

	/**
	 * Inserts the string representation of the <code>Object</code> argument
	 * into this character sequence.
	 * <p>
	 * The second argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * inserted into this sequence at the indicated offset.
	 * <p>
	 * The offset argument must be greater than or equal to <code>0</code>, and
	 * less than or equal to the length of this sequence.
	 *
	 * @param offset
	 *            the offset.
	 * @param obj
	 *            an <code>Object</code>.
	 * @return a reference to this object.
	 * @throws StringIndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int offset, Object obj) {
		return insert(offset, String.valueOf(obj));
	}

	/**
	 * Inserts the string into this character sequence.
	 * <p>
	 * The characters of the <code>String</code> argument are inserted, in
	 * order, into this sequence at the indicated offset, moving up any
	 * characters originally above that position and increasing the length of
	 * this sequence by the length of the argument. If <code>str</code> is
	 * <code>null</code>, then the four characters <code>"null"</code> are
	 * inserted into this sequence.
	 * <p>
	 * The character at index <i>k</i> in the new character sequence is equal
	 * to:
	 * <ul>
	 * <li>the character at index <i>k</i> in the old character sequence, if
	 * <i>k</i> is less than <code>offset</code>
	 * <li>the character at index <i>k</i><code>-offset</code> in the argument
	 * <code>str</code>, if <i>k</i> is not less than <code>offset</code> but is
	 * less than <code>offset+str.length()</code>
	 * <li>the character at index <i>k</i><code>-str.length()</code> in the old
	 * character sequence, if <i>k</i> is not less than
	 * <code>offset+str.length()</code>
	 * </ul>
	 * <p>
	 * The offset argument must be greater than or equal to <code>0</code>, and
	 * less than or equal to the length of this sequence.
	 *
	 * @param offset
	 *            the offset.
	 * @param str
	 *            a string.
	 * @return a reference to this object.
	 * @throws StringIndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int offset, String str) {
		if ((offset < 0) || (offset > length()))
			throw new StringIndexOutOfBoundsException(offset);
		if (str == null)
			str = "null";
		int len = str.length();
		int newCount = count + len;
		if (newCount > value.length)
			expandCapacity(newCount);
		System.arraycopy(value, offset, value, offset + len, count - offset);
		str.getChars(value, offset);
		count = newCount;
		return this;
	}

	/**
	 * Inserts the string representation of the <code>char</code> array argument
	 * into this sequence.
	 * <p>
	 * The characters of the array argument are inserted into the contents of
	 * this sequence at the position indicated by <code>offset</code>. The
	 * length of this sequence increases by the length of the argument.
	 * <p>
	 * The overall effect is exactly as if the argument were converted to a
	 * string by the method {@link String#valueOf(char[])} and the characters of
	 * that string were then {@link #insert(int,String) inserted} into this
	 * character sequence at the position indicated by <code>offset</code>.
	 *
	 * @param offset
	 *            the offset.
	 * @param str
	 *            a character array.
	 * @return a reference to this object.
	 * @throws StringIndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int offset, char str[]) {
		if ((offset < 0) || (offset > length()))
			throw new StringIndexOutOfBoundsException(offset);
		int len = str.length;
		int newCount = count + len;
		if (newCount > value.length)
			expandCapacity(newCount);
		System.arraycopy(value, offset, value, offset + len, count - offset);
		System.arraycopy(str, 0, value, offset, len);
		count = newCount;
		return this;
	}

	/**
	 * Inserts the specified <code>CharSequence</code> into this sequence.
	 * <p>
	 * The characters of the <code>CharSequence</code> argument are inserted, in
	 * order, into this sequence at the indicated offset, moving up any
	 * characters originally above that position and increasing the length of
	 * this sequence by the length of the argument s.
	 * <p>
	 * The result of this method is exactly the same as if it were an invocation
	 * of this object's insert(dstOffset, s, 0, s.length()) method.
	 *
	 * <p>
	 * If <code>s</code> is <code>null</code>, then the four characters
	 * <code>"null"</code> are inserted into this sequence.
	 *
	 * @param dstOffset
	 *            the offset.
	 * @param s
	 *            the sequence to be inserted
	 * @return a reference to this object.
	 * @throws IndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int dstOffset, CharSequence s) {
		if (s == null)
			s = "null";
		if (s instanceof String)
			return this.insert(dstOffset, (String) s);
		return this.insert(dstOffset, s, 0, s.length());
	}

	/**
	 * Inserts a subsequence of the specified <code>CharSequence</code> into
	 * this sequence.
	 * <p>
	 * The subsequence of the argument <code>s</code> specified by
	 * <code>start</code> and <code>end</code> are inserted, in order, into this
	 * sequence at the specified destination offset, moving up any characters
	 * originally above that position. The length of this sequence is increased
	 * by <code>end - start</code>.
	 * <p>
	 * The character at index <i>k</i> in this sequence becomes equal to:
	 * <ul>
	 * <li>the character at index <i>k</i> in this sequence, if <i>k</i> is less
	 * than <code>dstOffset</code>
	 * <li>the character at index <i>k</i><code>+start-dstOffset</code> in the
	 * argument <code>s</code>, if <i>k</i> is greater than or equal to
	 * <code>dstOffset</code> but is less than <code>dstOffset+end-start</code>
	 * <li>the character at index <i>k</i><code>-(end-start)</code> in this
	 * sequence, if <i>k</i> is greater than or equal to
	 * <code>dstOffset+end-start</code>
	 * </ul>
	 * <p>
	 * The dstOffset argument must be greater than or equal to <code>0</code>,
	 * and less than or equal to the length of this sequence.
	 * <p>
	 * The start argument must be nonnegative, and not greater than
	 * <code>end</code>.
	 * <p>
	 * The end argument must be greater than or equal to <code>start</code>, and
	 * less than or equal to the length of s.
	 *
	 * <p>
	 * If <code>s</code> is <code>null</code>, then this method inserts
	 * characters as if the s parameter was a sequence containing the four
	 * characters <code>"null"</code>.
	 *
	 * @param dstOffset
	 *            the offset in this sequence.
	 * @param s
	 *            the sequence to be inserted.
	 * @param start
	 *            the starting index of the subsequence to be inserted.
	 * @param end
	 *            the end index of the subsequence to be inserted.
	 * @return a reference to this object.
	 * @throws IndexOutOfBoundsException
	 *             if <code>dstOffset</code> is negative or greater than
	 *             <code>this.length()</code>, or <code>start</code> or
	 *             <code>end</code> are negative, or <code>start</code> is
	 *             greater than <code>end</code> or <code>end</code> is greater
	 *             than <code>s.length()</code>
	 */
	public AbstractStringBuilder insert(int dstOffset, CharSequence s,
			int start, int end) {
		if (s == null)
			s = "null";
		if ((dstOffset < 0) || (dstOffset > this.length()))
			throw new IndexOutOfBoundsException("dstOffset " + dstOffset);
		if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
			throw new IndexOutOfBoundsException("start " + start + ", end "
					+ end + ", s.length() " + s.length());
		int len = end - start;
		if (len == 0)
			return this;
		int newCount = count + len;
		if (newCount > value.length)
			expandCapacity(newCount);
		System.arraycopy(value, dstOffset, value, dstOffset + len, count
				- dstOffset);
		for (int i = start; i < end; i++)
			value[dstOffset++] = s.charAt(i);
		count = newCount;
		return this;
	}

	/**
	 * Inserts the string representation of the <code>boolean</code> argument
	 * into this sequence.
	 * <p>
	 * The second argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * inserted into this sequence at the indicated offset.
	 * <p>
	 * The offset argument must be greater than or equal to <code>0</code>, and
	 * less than or equal to the length of this sequence.
	 *
	 * @param offset
	 *            the offset.
	 * @param b
	 *            a <code>boolean</code>.
	 * @return a reference to this object.
	 * @throws StringIndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int offset, boolean b) {
		return insert(offset, String.valueOf(b));
	}

	/**
	 * Inserts the string representation of the <code>char</code> argument into
	 * this sequence.
	 * <p>
	 * The second argument is inserted into the contents of this sequence at the
	 * position indicated by <code>offset</code>. The length of this sequence
	 * increases by one.
	 * <p>
	 * The overall effect is exactly as if the argument were converted to a
	 * string by the method {@link String#valueOf(char)} and the character in
	 * that string were then {@link #insert(int, String) inserted} into this
	 * character sequence at the position indicated by <code>offset</code>.
	 * <p>
	 * The offset argument must be greater than or equal to <code>0</code>, and
	 * less than or equal to the length of this sequence.
	 *
	 * @param offset
	 *            the offset.
	 * @param c
	 *            a <code>char</code>.
	 * @return a reference to this object.
	 * @throws IndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int offset, char c) {
		int newCount = count + 1;
		if (newCount > value.length)
			expandCapacity(newCount);
		System.arraycopy(value, offset, value, offset + 1, count - offset);
		value[offset] = c;
		count = newCount;
		return this;
	}

	/**
	 * Inserts the string representation of the second <code>int</code> argument
	 * into this sequence.
	 * <p>
	 * The second argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * inserted into this sequence at the indicated offset.
	 * <p>
	 * The offset argument must be greater than or equal to <code>0</code>, and
	 * less than or equal to the length of this sequence.
	 *
	 * @param offset
	 *            the offset.
	 * @param i
	 *            an <code>int</code>.
	 * @return a reference to this object.
	 * @throws StringIndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int offset, int i) {
		return insert(offset, String.valueOf(i));
	}

	/**
	 * Inserts the string representation of the <code>long</code> argument into
	 * this sequence.
	 * <p>
	 * The second argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * inserted into this sequence at the position indicated by
	 * <code>offset</code>.
	 * <p>
	 * The offset argument must be greater than or equal to <code>0</code>, and
	 * less than or equal to the length of this sequence.
	 *
	 * @param offset
	 *            the offset.
	 * @param l
	 *            a <code>long</code>.
	 * @return a reference to this object.
	 * @throws StringIndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int offset, long l) {
		return insert(offset, String.valueOf(l));
	}

	/**
	 * Inserts the string representation of the <code>float</code> argument into
	 * this sequence.
	 * <p>
	 * The second argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * inserted into this sequence at the indicated offset.
	 * <p>
	 * The offset argument must be greater than or equal to <code>0</code>, and
	 * less than or equal to the length of this sequence.
	 *
	 * @param offset
	 *            the offset.
	 * @param f
	 *            a <code>float</code>.
	 * @return a reference to this object.
	 * @throws StringIndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int offset, float f) {
		return insert(offset, String.valueOf(f));
	}

	/**
	 * Inserts the string representation of the <code>double</code> argument
	 * into this sequence.
	 * <p>
	 * The second argument is converted to a string as if by the method
	 * <code>String.valueOf</code>, and the characters of that string are then
	 * inserted into this sequence at the indicated offset.
	 * <p>
	 * The offset argument must be greater than or equal to <code>0</code>, and
	 * less than or equal to the length of this sequence.
	 *
	 * @param offset
	 *            the offset.
	 * @param d
	 *            a <code>double</code>.
	 * @return a reference to this object.
	 * @throws StringIndexOutOfBoundsException
	 *             if the offset is invalid.
	 */
	public AbstractStringBuilder insert(int offset, double d) {
		return insert(offset, String.valueOf(d));
	}

	/**
	 * Returns the index within this string of the first occurrence of the
	 * specified substring. The integer returned is the smallest value <i>k</i>
	 * such that: <blockquote>
	 * 
	 * <pre>
	 * this.toString().startsWith(str, <i>k</i>)
	 * </pre>
	 * 
	 * </blockquote> is <code>true</code>.
	 *
	 * @param str
	 *            any string.
	 * @return if the string argument occurs as a substring within this object,
	 *         then the index of the first character of the first such substring
	 *         is returned; if it does not occur as a substring, <code>-1</code>
	 *         is returned.
	 * @throws java.lang.NullPointerException
	 *             if <code>str</code> is <code>null</code>.
	 */
	public int indexOf(String str) {
		return indexOf(str, 0);
	}

	/**
	 * Returns the index within this string of the first occurrence of the
	 * specified substring, starting at the specified index. The integer
	 * returned is the smallest value <tt>k</tt> for which: <blockquote>
	 * 
	 * <pre>
	 * k &gt;= Math.min(fromIndex, str.length()) &amp;&amp; this.toString().startsWith(str, k)
	 * </pre>
	 * 
	 * </blockquote> If no such value of <i>k</i> exists, then -1 is returned.
	 *
	 * @param str
	 *            the substring for which to search.
	 * @param fromIndex
	 *            the index from which to start the search.
	 * @return the index within this string of the first occurrence of the
	 *         specified substring, starting at the specified index.
	 * @throws java.lang.NullPointerException
	 *             if <code>str</code> is <code>null</code>.
	 */
	public int indexOf(String str, int fromIndex) {
		return String.indexOf(value, 0, count, str.toCharArray(), 0,
				str.length(), fromIndex);
	}

	/**
	 * Returns the index within this string of the rightmost occurrence of the
	 * specified substring. The rightmost empty string "" is considered to occur
	 * at the index value <code>this.length()</code>. The returned index is the
	 * largest value <i>k</i> such that <blockquote>
	 * 
	 * <pre>
	 * this.toString().startsWith(str, k)
	 * </pre>
	 * 
	 * </blockquote> is true.
	 *
	 * @param str
	 *            the substring to search for.
	 * @return if the string argument occurs one or more times as a substring
	 *         within this object, then the index of the first character of the
	 *         last such substring is returned. If it does not occur as a
	 *         substring, <code>-1</code> is returned.
	 * @throws java.lang.NullPointerException
	 *             if <code>str</code> is <code>null</code>.
	 */
	public int lastIndexOf(String str) {
		return lastIndexOf(str, count);
	}

	/**
	 * Returns the index within this string of the last occurrence of the
	 * specified substring. The integer returned is the largest value <i>k</i>
	 * such that: <blockquote>
	 * 
	 * <pre>
	 * k &lt;= Math.min(fromIndex, str.length()) &amp;&amp; this.toString().startsWith(str, k)
	 * </pre>
	 * 
	 * </blockquote> If no such value of <i>k</i> exists, then -1 is returned.
	 * 
	 * @param str
	 *            the substring to search for.
	 * @param fromIndex
	 *            the index to start the search from.
	 * @return the index within this sequence of the last occurrence of the
	 *         specified substring.
	 * @throws java.lang.NullPointerException
	 *             if <code>str</code> is <code>null</code>.
	 */
	public int lastIndexOf(String str, int fromIndex) {
		return String.lastIndexOf(value, 0, count, str.toCharArray(), 0,
				str.length(), fromIndex);
	}

	/**
	 * Causes this character sequence to be replaced by the reverse of the
	 * sequence. If there are any surrogate pairs included in the sequence,
	 * these are treated as single characters for the reverse operation. Thus,
	 * the order of the high-low surrogates is never reversed.
	 *
	 * Let <i>n</i> be the character length of this character sequence (not the
	 * length in <code>char</code> values) just prior to execution of the
	 * <code>reverse</code> method. Then the character at index <i>k</i> in the
	 * new character sequence is equal to the character at index <i>n-k-1</i> in
	 * the old character sequence.
	 *
	 * <p>
	 * Note that the reverse operation may result in producing surrogate pairs
	 * that were unpaired low-surrogates and high-surrogates before the
	 * operation. For example, reversing "&#92;uDC00&#92;uD800" produces
	 * "&#92;uD800&#92;uDC00" which is a valid surrogate pair.
	 *
	 * @return a reference to this object.
	 */
	public AbstractStringBuilder reverse() {
		boolean hasSurrogate = false;
		int n = count - 1;
		for (int j = (n - 1) >> 1; j >= 0; --j) {
			char temp = value[j];
			char temp2 = value[n - j];
			if (!hasSurrogate) {
				hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
						|| (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
			}
			value[j] = temp2;
			value[n - j] = temp;
		}
		if (hasSurrogate) {
			// Reverse back all valid surrogate pairs
			for (int i = 0; i < count - 1; i++) {
				char c2 = value[i];
				if (Character.isLowSurrogate(c2)) {
					char c1 = value[i + 1];
					if (Character.isHighSurrogate(c1)) {
						value[i++] = c1;
						value[i] = c2;
					}
				}
			}
		}
		return this;
	}

	/**
	 * Returns a string representing the data in this sequence. A new
	 * <code>String</code> object is allocated and initialized to contain the
	 * character sequence currently represented by this object. This
	 * <code>String</code> is then returned. Subsequent changes to this sequence
	 * do not affect the contents of the <code>String</code>.
	 *
	 * @return a string representation of this sequence of characters.
	 */
	public abstract String toString();

	/**
	 * Needed by <tt>String</tt> for the contentEquals method.
	 */
	final char[] getValue() {
		return value;
	}

}
